#include "inputCommand.h"
#include <wiringSerial.h>
#include <wiringPi.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include "msg_queue.h"

#include <stdio.h>


int socketInit(struct inputCommand* command,char *name ,char *ipAddress, int port);
int socketGetCommand(struct inputCommand* command,char *cmd);

struct inputCommand socketCommand = {
    .commandName = "socketDevice",
    .command = {'\0'},
    .Init = socketInit,
    .getCommand = socketGetCommand,
    .sendCommand = socketSendCommand,
    .log = {'\0'},
    .Next = NULL
};

int socketInit(struct inputCommand* command,char *name ,char *ipAddress, int port)
{
    int server_fd;
    struct sockaddr_in address;
    int addrlen = sizeof(address);


    // 1、 创建socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY; // 监听所有ip
    address.sin_port = htons(port);
    // 2、 绑定
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    printf("绑定成功，端口号%d\r\n",port);
    // 3、 监听
    if (listen(server_fd, 1) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    printf("socket Server is running ....\n");
    command->sfd = server_fd;
    return server_fd;
}

int socketSendCommand(struct inputCommand* command,char *cmd)
{

}

int socketGetCommand(struct inputCommand* command,char *cmd)
{

    int keepalive = 1; // 开启TCP_KEEPALIVE选项
    int keepidle = 10; // 设置探测时间间隔为10秒
    int keepinterval = 5; // 设置探测包发送间隔为5秒
    int keepcount = 3; // 设置探测包发送次数为3次

    int new_socket;
    int nread = 0;
    struct sockaddr_in address;
    memset(&address,0,sizeof(struct sockaddr_in));
    int addrlen = sizeof(struct sockaddr_in);
    printf("%s thread start\n", __func__);
   
    mqd_t mqd = (mqd_t)*cmd;
    printf("mqd=%d\n",mqd);
    int ret = -1;
    while(1)
    {
        if ((new_socket = accept(command->sfd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0)
        {
            perror("accept");
            exit(EXIT_FAILURE);
        }

        if(-1 == new_socket)
            continue;
        ret = setsockopt(new_socket, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)); // 设置TCP_KEEPALIVE选项
        if (ret == -1) { // 如果设置失败，打印错误信息并跳出循环
            perror("setsockopt");
            break;
        }
        ret = setsockopt(new_socket, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle)); // 设置探测时间间隔选项
        if (ret == -1) { // 如果设置失败，打印错误信息并跳出循环
            perror("setsockopt");
            break;
        }
        ret = setsockopt(new_socket, IPPROTO_TCP, TCP_KEEPINTVL, &keepinterval, sizeof(keepinterval)); // 设置探测包发送间隔选项
        if (ret == -1) { // 如果设置失败，打印错误信息并跳出循环
            perror("setsockopt");
            break;
        }
        ret = setsockopt(new_socket, IPPROTO_TCP, TCP_KEEPCNT, &keepcount, sizeof(keepcount)); // 设置探测包发送次数选项
        if (ret == -1) { // 如果设置失败，打印错误信息并跳出循环
            perror("setsockopt");
            break;
        }
        
        printf("Accepted a connection from %s:%d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port)); // 打印客户端的IP地址和端口号

        while (1) 
        {
            memset(command->command,'\0',sizeof(command->command));
            ret = recv(new_socket, command->command,sizeof(command->command), 0);
            printf("ret = %d\n",ret);
            printf("%s|%s|%d:\n", __FILE__, __func__, __LINE__);
            if (ret > 0)
            {
                printf("recv:%s\n",command->command);
                if(ret == 6 && command->command[0]== 0x09 && command->command[1]== 0x08 && command->command[4]== 0x08 && command->command[5]== 0x09)
                {
                    if(send_message(mqd,command->command,ret) == -1)
                    {
                        printf("send faild\n");
                    }else
                    printf("voice commite to msg_queue,%d\n,",command->command[0]=='9');
                }
                

            }
            else if ( -1 == ret || 0 == ret)
            {
                perror("close");
                break;
            }
        }
    }


}




struct inputCommand* addSocketToInputCommandLink(struct inputCommand* phead)
{
    if(phead == NULL)
    {
        return &socketCommand;
    }
    else
    {
        socketCommand.Next = phead;
        phead = &socketCommand;
        return phead;
    }

}


